#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
提示词生成引擎模块

该模块实现了提示词生成的核心逻辑，根据融合的信息和提示词模板生成最终的提示词。
"""

import logging
from typing import Dict, List, Optional
from src.text.prompt_generator.prompt_template_manager import get_prompt_template_manager
from src.text.prompt_generator.information_fusion_processor import get_information_fusion_processor

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


class PromptGenerationEngine:
    """
    提示词生成引擎类
    
    负责根据融合的信息和提示词模板生成最终的提示词，是提示词生成器的核心组件。
    """
    
    def __init__(self):
        """
        初始化提示词生成引擎
        
        加载提示词模板管理器和信息融合处理器
        """
        self.template_manager = get_prompt_template_manager()
        self.fusion_processor = get_information_fusion_processor()
        logger.info("提示词生成引擎初始化完成")
    
    def generate_prompt(self, video_id: str, vision_analysis_result: Dict, category: str) -> str:
        """
        生成提示词
        
        Args:
            video_id: 视频ID
            vision_analysis_result: 视觉分析结果
            category: 编码类目
            
        Returns:
            生成的提示词
            
        Raises:
            ValueError: 当输入参数无效时
        """
        if not video_id or not vision_analysis_result or not category:
            raise ValueError("视频ID、视觉分析结果和编码类目都不能为空")
        
        logger.info(f"为视频 {video_id} 和类目 {category} 生成提示词")
        
        # 步骤1: 融合信息
        fusion_result = self.fusion_processor.fuse_information(video_id, vision_analysis_result)
        
        # 步骤2: 获取提示词模板
        template = self.template_manager.get_template(category)
        
        # 步骤3: 生成提示词
        prompt = self._build_prompt(template, fusion_result, category)
        
        logger.info(f"提示词生成成功，长度: {len(prompt)} 字符")
        return prompt
    
    def _build_prompt(self, template: str, fusion_result: Dict, category: str) -> str:
        """
        根据模板和融合结果构建提示词
        
        Args:
            template: 提示词模板
            fusion_result: 信息融合结果
            category: 编码类目
            
        Returns:
            构建好的提示词
        """
        # 提取融合结果中的信息
        formatted_known_info = fusion_result.get('formatted_known_info', '')
        required_categories = fusion_result.get('required_categories', [])
        
        # 确保目标类目在需要补充的类目中
        if category not in required_categories:
            # 如果目标类目已有值，构建一个简单的确认提示词
            return self._build_confirmation_prompt(category, fusion_result)
        
        # 构建提示词内容
        prompt_parts = []
        
        # 添加任务说明
        task_description = f"请分析视频内容，确定其{self._get_category_description(category)}。"
        prompt_parts.append(task_description)
        
        # 添加已知信息
        if formatted_known_info:
            prompt_parts.append(f"已知信息：{formatted_known_info}")
        
        # 添加提示词模板内容
        prompt_parts.append(template)
        
        # 添加输出格式要求
        output_format = "请确保你的回答简洁明了，直接给出最符合视频内容的答案。"
        prompt_parts.append(output_format)
        
        # 组合所有部分
        return "\n\n".join(prompt_parts)
    
    def _build_confirmation_prompt(self, category: str, fusion_result: Dict) -> str:
        """
        构建确认类型的提示词（当目标类目已有值时）
        
        Args:
            category: 编码类目
            fusion_result: 信息融合结果
            
        Returns:
            确认类型的提示词
        """
        context_info = fusion_result.get('context_info', {})
        current_value = context_info.get(category, '')
        
        prompt_parts = [
            f"请确认视频的{self._get_category_description(category)}是否正确。",
            f"当前识别结果：{current_value}",
            "如果正确，请直接回答当前结果；如果不正确，请分析视频内容并给出正确答案。"
        ]
        
        return "\n\n".join(prompt_parts)
    
    def _get_category_description(self, category: str) -> str:
        """
        获取编码类目的中文描述
        
        Args:
            category: 编码类目
            
        Returns:
            类目的中文描述
        """
        category_descriptions = {
            'scene_setting': '场景设定',
            'theme_type': '主题类型',
            'emotional_tendency': '情感倾向',
            'content_category': '内容类别',
            'violence_level': '暴力程度',
            'sensitive_content': '敏感内容',
            'target_audience': '目标受众'
        }
        return category_descriptions.get(category, category)
    
    def batch_generate_prompts(self, video_id: str, vision_analysis_result: Dict, categories: List[str]) -> Dict[str, str]:
        """
        批量生成多个类目的提示词
        
        Args:
            video_id: 视频ID
            vision_analysis_result: 视觉分析结果
            categories: 需要生成提示词的类目列表
            
        Returns:
            类目到提示词的映射
        """
        if not categories:
            logger.warning("类目列表为空，跳过批量生成")
            return {}
        
        logger.info(f"为视频 {video_id} 批量生成 {len(categories)} 个类目提示词")
        
        # 只需要融合一次信息
        fusion_result = self.fusion_processor.fuse_information(video_id, vision_analysis_result)
        
        # 为每个类目生成提示词
        prompts = {}
        for category in categories:
            try:
                template = self.template_manager.get_template(category)
                prompt = self._build_prompt(template, fusion_result, category)
                prompts[category] = prompt
                logger.info(f"类目 {category} 提示词生成成功")
            except Exception as e:
                logger.error(f"类目 {category} 提示词生成失败: {str(e)}")
                # 生成一个默认提示词
                prompts[category] = self._generate_default_prompt(category)
        
        return prompts
    
    def _generate_default_prompt(self, category: str) -> str:
        """
        生成默认提示词（当模板获取失败时）
        
        Args:
            category: 编码类目
            
        Returns:
            默认提示词
        """
        default_template = self.template_manager.get_default_template()
        description = self._get_category_description(category)
        
        prompt_parts = [
            f"请分析视频内容，确定其{description}。",
            default_template,
            "请确保你的回答简洁明了，直接给出最符合视频内容的答案。"
        ]
        
        return "\n\n".join(prompt_parts)
    
    def validate_prompt(self, prompt: str) -> bool:
        """
        验证生成的提示词是否有效
        
        Args:
            prompt: 生成的提示词
            
        Returns:
            提示词是否有效
        """
        if not prompt or len(prompt.strip()) == 0:
            logger.error("提示词为空或仅包含空白字符")
            return False
        
        if len(prompt) < 50:
            logger.warning(f"提示词过短: {len(prompt)} 字符")
            # 不返回False，因为某些简单场景可能需要短提示词
        
        if len(prompt) > 2000:
            logger.error(f"提示词过长: {len(prompt)} 字符")
            return False
        
        logger.info(f"提示词验证通过，长度: {len(prompt)} 字符")
        return True


# 单例模式访问函数
_prompt_generation_engine_instance = None


def get_prompt_generation_engine() -> PromptGenerationEngine:
    """
    获取提示词生成引擎的单例实例
    
    Returns:
        PromptGenerationEngine实例
    """
    global _prompt_generation_engine_instance
    if _prompt_generation_engine_instance is None:
        _prompt_generation_engine_instance = PromptGenerationEngine()
    return _prompt_generation_engine_instance


# 测试代码
if __name__ == "__main__":
    try:
        # 创建测试用的视觉分析结果
        test_vision_result = {
            'scene_setting': '校园场景',
            'key_elements': ['学生', '教室', '黑板']
        }
        
        # 获取生成引擎实例
        engine = get_prompt_generation_engine()
        
        # 测试单个提示词生成
        print("测试单个提示词生成...")
        prompt = engine.generate_prompt('video_001', test_vision_result, 'theme_type')
        print(f"生成的提示词:\n{prompt}")
        print(f"提示词有效性: {engine.validate_prompt(prompt)}")
        print()
        
        # 测试批量提示词生成
        print("测试批量提示词生成...")
        categories = ['theme_type', 'emotional_tendency', 'target_audience']
        batch_prompts = engine.batch_generate_prompts('video_001', test_vision_result, categories)
        
        for cat, p in batch_prompts.items():
            print(f"\n类目 {cat} 的提示词:\n{p[:100]}...")  # 只打印前100个字符
        
    except Exception as e:
        logger.error(f"测试失败: {str(e)}")
        raise